package org.xxpay.service.impl;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.xxpay.core.common.constant.MchConstant;
import org.xxpay.core.common.util.AssignWeightUtil;
import org.xxpay.core.entity.*;
import org.xxpay.core.service.IMchAgentpayPassageService;
import org.xxpay.core.service.ISysConfigService;
import org.xxpay.service.dao.mapper.AgentpayPassageMapper;
import org.xxpay.service.dao.mapper.MchAgentpayPassageMapper;
import org.xxpay.service.dao.mapper.MchAgentpayRecordMapper;
import org.xxpay.service.dao.mapper.MchInfoMapper;

import java.util.*;

/**
 * @author: dingzhiwei
 * @date: 2018/5/3
 * @description: 商户代付通道
 */
@Service
public class MchAgentpayPassageServiceImpl implements IMchAgentpayPassageService {

    @Autowired
    private MchAgentpayPassageMapper mchAgentpayPassageMapper;

    @Autowired
    private AgentpayPassageMapper agentpayPassageMapper;

    @Autowired
    private MchInfoMapper mchInfoMapper;

    @Autowired
    private ISysConfigService sysConfigService;

    @Autowired
    private MchAgentpayRecordMapper mchAgentpayRecordMapper;

    @Override
    public int add(MchAgentpayPassage mchAgentpayPassage) {
        return mchAgentpayPassageMapper.insertSelective(mchAgentpayPassage);
    }

    @Override
    public int update(MchAgentpayPassage mchAgentpayPassage) {
        return mchAgentpayPassageMapper.updateByPrimaryKeySelective(mchAgentpayPassage);
    }

    @Override
    public int updateByMchId(MchAgentpayPassage updateMchAgentpayPassage, Long mchId) {
        MchAgentpayPassage mchAgentpayPassage = new MchAgentpayPassage();
        mchAgentpayPassage.setMchId(mchId);
        MchAgentpayPassageExample example = new MchAgentpayPassageExample();
        MchAgentpayPassageExample.Criteria criteria = example.createCriteria();
        criteria.andMchIdEqualTo(mchId);
        return mchAgentpayPassageMapper.updateByExampleSelective(updateMchAgentpayPassage, example);
    }

    @Override
    public MchAgentpayPassage findById(Integer id) {
        return mchAgentpayPassageMapper.selectByPrimaryKey(id);
    }

    @Override
    public MchAgentpayPassage findByMchIdAndAgentpayPassageId(Long mchId, Integer agentpayPassageId) {
        MchAgentpayPassage mchAgentpayPassage = new MchAgentpayPassage();
        mchAgentpayPassage.setMchId(mchId);
        mchAgentpayPassage.setAgentpayPassageId(agentpayPassageId);
        List<MchAgentpayPassage> mchAgentpayPassageList = selectAll(mchAgentpayPassage);
        if(CollectionUtils.isEmpty(mchAgentpayPassageList)) return null;
        return mchAgentpayPassageList.get(0);
    }

    @Override
    public List<MchAgentpayPassage> select(int offset, int limit, MchAgentpayPassage mchAgentpayPassage) {
        MchAgentpayPassageExample example = new MchAgentpayPassageExample();
        example.setOrderByClause("createTime DESC");
        example.setOffset(offset);
        example.setLimit(limit);
        MchAgentpayPassageExample.Criteria criteria = example.createCriteria();
        setCriteria(criteria, mchAgentpayPassage);
        return mchAgentpayPassageMapper.selectByExample(example);
    }

    @Override
    public Integer count(MchAgentpayPassage mchAgentpayPassage) {
        MchAgentpayPassageExample example = new MchAgentpayPassageExample();
        MchAgentpayPassageExample.Criteria criteria = example.createCriteria();
        setCriteria(criteria, mchAgentpayPassage);
        return mchAgentpayPassageMapper.countByExample(example);
    }

    @Override
    public List<MchAgentpayPassage> selectAll(MchAgentpayPassage mchAgentpayPassage) {
        return selectAll(mchAgentpayPassage, "createTime DESC");
    }

    public List<MchAgentpayPassage> selectAll(MchAgentpayPassage mchAgentpayPassage, String OrderByClause) {
        MchAgentpayPassageExample example = new MchAgentpayPassageExample();
        example.setOrderByClause(OrderByClause);
        MchAgentpayPassageExample.Criteria criteria = example.createCriteria();
        setCriteria(criteria, mchAgentpayPassage);
        return mchAgentpayPassageMapper.selectByExample(example);
    }

    @Override
    public List<MchAgentpayPassage> selectAllByMchId(Long mchId) {
        MchAgentpayPassage mchAgentpayPassage = new MchAgentpayPassage();
        mchAgentpayPassage.setMchId(mchId);
        return selectAll(mchAgentpayPassage);
    }

    @Override
    public List<MchAgentpayPassage> selectAvailable(Long mchId) {
        // TODO 以下逻辑可以优化为sql关联查询实现
        MchAgentpayPassage mchAgentpayPassage = new MchAgentpayPassage();
        mchAgentpayPassage.setMchId(mchId);
        mchAgentpayPassage.setStatus(MchConstant.PUB_YES);
        // 得到商户已经配置的代付通道
        List<MchAgentpayPassage> mchAgentpayPassageList = selectAll(mchAgentpayPassage, "isDefault DESC");
        if(CollectionUtils.isEmpty(mchAgentpayPassageList)) return mchAgentpayPassageList;
        List<Integer> ids = new LinkedList<>();
        for(MchAgentpayPassage mchAgentpayPassage1 : mchAgentpayPassageList) {
            ids.add(mchAgentpayPassage1.getAgentpayPassageId());
        }
        // 查询商户配的,有开启的代付通道
        AgentpayPassageExample example = new AgentpayPassageExample();
        AgentpayPassageExample.Criteria criteria = example.createCriteria();
        criteria.andIdIn(ids);
        criteria.andStatusEqualTo(MchConstant.PUB_YES);

        MchInfo mchInfo = mchInfoMapper.selectByPrimaryKey(mchId);
        if(mchInfo.getType() == MchConstant.MCH_TYPE_PRIVATE){ //如果私有商户， 需判断可用接口类型

            List<String> supportIfTypeCodeList = mchInfo.getSupportIfTypeList();
            if(supportIfTypeCodeList.isEmpty()) {
                criteria.andIdIsNull(); //添加查询条件 1 != 1 ， 查询无结果
            }else{
                criteria.andIfTypeCodeIn(supportIfTypeCodeList);
            }
        }
        List<AgentpayPassage> agentpayPassageList = agentpayPassageMapper.selectByExample(example);
        // 如果为空,则返回空代付通道
        if(CollectionUtils.isEmpty(agentpayPassageList)) {
            return null;
        }
        Map<String, AgentpayPassage> map = new HashMap<>();
        for(AgentpayPassage agentpayPassage : agentpayPassageList) {
            map.put(agentpayPassage.getId()+"", agentpayPassage);
        }
        List<MchAgentpayPassage> list = new LinkedList<>();
        for(MchAgentpayPassage mp : mchAgentpayPassageList) {
            if(map.get(String.valueOf(mp.getAgentpayPassageId())) != null) {
                list.add(mp);
            }
        }
        //null || 仅包含一个，无需判断 默认还是权重
        if(list == null || list.size() <= 1){
            return list;
        }

        //查询代付的默认配置
        Integer agentpayMchConfigFlag = sysConfigService.getDBAgentpayConfig().getAgentpayMchConfigFlag();

        //商户默认配置
        if(agentpayMchConfigFlag == MchConstant.AGENTPAY_MCH_CONFIG_FLAG_DEFAULT){

            return list; // 返回有效的商户代付通道

        }else if(agentpayMchConfigFlag == MchConstant.AGENTPAY_MCH_CONFIG_FLAG_ORDERS_WEIGHT){ //轮询


            //订单查询时间
            Integer agentpayMchConfig2QueryOrderTime = sysConfigService.getDBAgentpayConfig().getAgentpayMchConfig2QueryOrderTime();

            //定义 通道ID 和 权重的map集合
            List<AssignWeightUtil.AssignWeight> assignWeightList = new ArrayList<>();
            List<Integer> queryPassageIdList = new ArrayList<>();

            list.stream().forEach(item -> {

                AssignWeightUtil.AssignWeight w = new AssignWeightUtil.AssignWeight();
                w.setName(item.getAgentpayPassageId() + "");
                w.setWeight(item.getPayWeight().intValue());
                assignWeightList.add(w);
                queryPassageIdList.add(item.getAgentpayPassageId());
            });

            //根据passageId集合 和统计时间参数 查询出订单量
            Map<String, Integer> queryPassageAndCountMap = new HashMap<>();
            List<Map> dbResult = mchAgentpayRecordMapper.countByMchAgentpayWeight(queryPassageIdList, agentpayMchConfig2QueryOrderTime);
            for (Map item : dbResult) {
                JSONObject jsonObject = new JSONObject(item);
                queryPassageAndCountMap.put(jsonObject.getString("passageId"), jsonObject.getIntValue("countNum"));
            }

            //赋值到AssignWeight对象
            for (AssignWeightUtil.AssignWeight assignWeight : assignWeightList) {

                Integer count = queryPassageAndCountMap.get(assignWeight.getName());
                assignWeight.setCount(count == null ? 0 : count);
            }

            List<MchAgentpayPassage> result = new ArrayList<>();

            //获取到可用的通道
            AssignWeightUtil.AssignWeight assignWeightResult = AssignWeightUtil.assignUniform(assignWeightList);

            //查询出可用通道并返回值
            Integer assignWeightResultPassageId = Integer.parseInt(assignWeightResult.getName());
            for (MchAgentpayPassage item : list) {
                if(item.getAgentpayPassageId().equals(assignWeightResultPassageId)){
                    result.add(item);
                    break;
                }
            }

            return result;
        }

        return null;

    }

    void setCriteria(MchAgentpayPassageExample.Criteria criteria, MchAgentpayPassage obj) {
        if(obj != null) {
            if(obj.getMchId() != null) criteria.andMchIdEqualTo(obj.getMchId());
            if(obj.getAgentpayPassageId() != null) criteria.andAgentpayPassageIdEqualTo(obj.getAgentpayPassageId());
            if(obj.getIsDefault() != null) criteria.andIsDefaultEqualTo(obj.getIsDefault());
            if(obj.getStatus() != null && obj.getStatus().byteValue() != -99) criteria.andStatusEqualTo(obj.getStatus());
        }
    }
}
